cmake_minimum_required(VERSION 3.10)

# message( "---> "  " CMake begin")
# message( "dir" ${PROJECT_SOURCE_DIR})

# Set project name
project(stm32f103c8)

#Set definitions
add_definitions(-DUSE_HAL_DRIVER)
add_definitions(-DSTM32F103xB)
add_definitions(-DUSE_STM32F1xx_NUCLEO)
# add_definitions(-DUSE_USB_FS)
# add_definitions(-DUSE_USB_HS)
# add_definitions(-DUSE_USB_HS_IN_FS)
# add_definitions(-D__TARGET_FPU_VFP)
# add_definitions(-D__GNUC__)

SET(USB_TYPE "HID" CACHE STRING "set USB type")

# Set include files directories
include_directories(
    ${PROJECT_SOURCE_DIR}/../Drivers/CMSIS/Core/Include
    ${PROJECT_SOURCE_DIR}/../Drivers/CMSIS/Device/ST/STM32F1xx/Include
    ${PROJECT_SOURCE_DIR}/../Drivers/STM32F1xx_HAL_Driver/Inc
    ${PROJECT_SOURCE_DIR}/../Drivers/STM32F1xx_HAL_Driver/Inc/Legacy
    ${PROJECT_SOURCE_DIR}/../Drivers/BSP/stm32f103c8
    ${PROJECT_SOURCE_DIR}/../Middlewares/ST/STM32_USB_Device_Library/Core/Inc
    ${PROJECT_SOURCE_DIR}/../Projects/stm32f103_cdc_vcp/Inc
    ${PROJECT_SOURCE_DIR}/../UserLib
)

if (USB_TYPE STREQUAL CDC)
    message("Use CDC USB")
    add_definitions(-DUSB_TYPE=1)
    include_directories(
        ${PROJECT_SOURCE_DIR}/../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc
    )
    file(GLOB USB_SRCS
        ${PROJECT_SOURCE_DIR}/../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc_dual.c
    )
else()
    message("Use HID USB")
    add_definitions(-DUSB_TYPE=2)
    include_directories(
        ${PROJECT_SOURCE_DIR}/../Middlewares/ST/STM32_USB_Device_Library/Class/HID/Inc
        # ${PROJECT_SOURCE_DIR}/../Usb/Inc/UsbHid
    )
    file(GLOB USB_SRCS
        ${PROJECT_SOURCE_DIR}/../Middlewares/ST/STM32_USB_Device_Library/Class/HID/Src/usbd_hid.c
        # ${PROJECT_SOURCE_DIR}/../Usb/Src/UsbHid/*.c
    )
endif()

# Set source files
# Driver source files
file(GLOB DRV_SRCS
    ${PROJECT_SOURCE_DIR}/../Drivers/BSP/stm32f103c8/*.c
    ${PROJECT_SOURCE_DIR}/../Drivers/STM32F1xx_HAL_Driver/Src/*.c
    ${PROJECT_SOURCE_DIR}/../Drivers/STM32F1xx_HAL_Driver/Src/Legacy/*.c
    ${PROJECT_SOURCE_DIR}/../Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_core.c
    ${PROJECT_SOURCE_DIR}/../Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ctlreq.c
    ${PROJECT_SOURCE_DIR}/../Middlewares/ST/STM32_USB_Device_Library/Core/Src/usbd_ioreq.c
)
# Remove unused source files from DRV_SRCS list
list(REMOVE_ITEM DRV_SRCS
    ${PROJECT_SOURCE_DIR}/../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_msp_template.c
    ${PROJECT_SOURCE_DIR}/../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_timebase_rtc_alarm_template.c
    ${PROJECT_SOURCE_DIR}/../Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_timebase_tim_template.c
)
# APP source files
file(GLOB APP_SRCS
    ${PROJECT_SOURCE_DIR}/../Projects/stm32f103_cdc_vcp/Src/*.c
    ${PROJECT_SOURCE_DIR}/../UserLib/uart.c
)
              
# Set startup assembly file 
set(STARTUP_FILE ${PROJECT_SOURCE_DIR}/../Drivers/CMSIS/Device/ST/STM32F1xx/Source/gcc/startup_stm32f103xb.s)
# Set link file
set(LINKER_SCRIPT ${PROJECT_SOURCE_DIR}/../Drivers/CMSIS/Device/ST/STM32F1xx/Source/gcc/linker/STM32F103XB_FLASH.ld)
set(DBG_FLAGS "-g -Os")

# Enable assembly compiler
enable_language(ASM)

# Set cross compiler and linker tools
include(${PROJECT_SOURCE_DIR}/arm-none-eabi-gcc.cmake)

#Uncomment for hardware floating point
# set(FPU_FLAGS "-mfloat-abi=hard -mfpu=fpv4-sp-d16")
# add_definitions(-DARM_MATH_CM4 -DARM_MATH_MATRIX_CHECK -DARM_MATH_ROUNDING)
# Set MCU architecture
# set(MCU_FLAGS "-mcpu=cortex-m4 ${FPU_FLAGS} -mthumb")
set(MCU_FLAGS "-mcpu=cortex-m3 -mthumb")
# Set link flag
set(LINK_FLAGS "${MCU_FLAGS} -Wl,-Map=${PROJECT_BINARY_DIR}/${PROJECT_NAME}.map,--cref -Wl,--gc-sections")
# Set compile and link flags
# set(CMAKE_ASM_FLAGS "-x assembler-with-cpp -g ${MCU_FLAGS} -O1 -nostartfiles -fstrict-volatile-bitfields -ffunction-sections -fdata-sections -Wl,--gc-sections -Wall -Wextra -Wstrict-prototypes")
# set(CMAKE_C_FLAGS "-g ${MCU_FLAGS} -O1 -nostartfiles -fstrict-volatile-bitfields -ffunction-sections -fdata-sections -Wl,--gc-sections -Wall -Wextra -Wstrict-prototypes")
# set(CMAKE_CXX_FLAGS "-g ${MCU_FLAGS} -O1 -nostartfiles -fstrict-volatile-bitfields -ffunction-sections -fdata-sections -Wl,--gc-sections -Wall -Wextra -Wstrict-prototypes")
set(CMAKE_ASM_FLAGS "${MCU_FLAGS} -x assembler-with-cpp ${DBG_FLAGS} " CACHE INTERNAL "ASM compiler flags")
# set(CMAKE_C_FLAGS "${MCU_FLAGS} -g -O1 -nostartfiles -fstrict-volatile-bitfields -ffunction-sections -fdata-sections -Wl,--gc-sections -Wall -Wextra -Wstrict-prototypes -std=gnu17")
set(CMAKE_C_FLAGS "${MCU_FLAGS} -std=gnu99 -Wall -fdata-sections -ffunction-sections ${DBG_FLAGS} " CACHE INTERNAL "C compiler flags")
# set(CMAKE_CXX_FLAGS "${MCU_FLAGS} -g -O1 -nostartfiles -fstrict-volatile-bitfields -ffunction-sections -fdata-sections -Wl,--gc-sections -Wall -Wextra -Wstrict-prototypes")
set(CMAKE_CXX_FLAGS "${MCU_FLAGS} -fno-rtti -fno-exceptions -fno-builtin -Wall -fdata-sections -ffunction-sections ${DBG_FLAGS} " CACHE INTERNAL "Cxx compiler flags")

set(CMAKE_EXE_LINKER_FLAGS "-Xlinker -T ${LINKER_SCRIPT} ${LINK_FLAGS}" CACHE INTERNAL "Exe linker flags")
# set(CMAKE_EXE_LINKER_FLAGS "-Xlinker -T ${LINKER_SCRIPT} ${LIBS_FLAG}")
# set(CMAKE_EXE_LINKER_FLAGS "${MCU_FLAGS}  -O1 -nostartfiles -fstrict-volatile-bitfields -ffunction-sections -fdata-sections -Wl,--gc-sections -Wall -Wextra -Wstrict-prototypes -g -T ${LINKER_SCRIPT} -nostartfiles -Xlinker --gc-sections -Wl,-Map=${PROJECT_BINARY_DIR}/${PROJECT_NAME}.map --specs=nosys.specs ${LIBS_FLAG}")
# set(CMAKE_EXE_LINKER_FLAGS "-Xlinker -T ${LINKER_SCRIPT} -Wl,-Map=${PROJECT_BINARY_DIR}/${PROJECT_NAME}.map -Wl,--gc-sections ${LIBS_FLAG}")

# Generate executable target file
add_executable(${PROJECT_NAME}.elf ${STARTUP_FILE} ${APP_SRCS} ${DRV_SRCS} ${USB_SRCS})

# message(STATUS "PROJECT_BINARY_DIR = ${PROJECT_BINARY_DIR}")
# message(STATUS "CMAKE_CURRENT_BINARY_DIR = ${CMAKE_CURRENT_BINARY_DIR}")

# User command: generate bin/hex files
add_custom_command(TARGET "${PROJECT_NAME}.elf" POST_BUILD
COMMAND ${CMAKE_OBJDUMP} -S ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.elf > ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.disasm
# COMMAND ${CMAKE_OBJDUMP} -t ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.elf > ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.sym
COMMAND ${CMAKE_OBJCOPY} -Obinary ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.elf ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.bin
COMMAND ${CMAKE_OBJCOPY} -Oihex ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.elf ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.hex
COMMENT "Building binary file and hex file"
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.bin "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.bin"
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.hex "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}.hex"
COMMAND ${CMAKE_SIZE} --format=berkeley ${PROJECT_NAME}.elf ${PROJECT_NAME}.hex
COMMENT "Invoking: Cross ARM GNU Print Size"
)

# # Generate the binary file
# add_custom_target(${PROJECT_BINARY_DIR}/${PROJECT_NAME}.bin  ALL ${CMAKE_OBJCOPY} -Obinary "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.elf" "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.bin" DEPENDS ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.elf)
# # Generate the hex file
# add_custom_target(${PROJECT_BINARY_DIR}/${PROJECT_NAME}.hex  ALL ${CMAKE_OBJCOPY} -Oihex   "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.elf" "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.hex" DEPENDS ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.elf)
# # Echo the size Infomation
# add_custom_target (size    ALL ${CMAKE_SIZE}               "${PROJECT_BINARY_DIR}/${PROJECT_NAME}.elf"                                                           DEPENDS ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.elf)
